package com.zc.utils.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zc.utils.WebSocketSubject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

/***
 * Web Scoket服务.
 * <ul>
 * URL expression as
 * <li>not use SSL , ws://host/{yourProjectName}/websocket/{principal}
 * <li>if use SSL , wss://host/{yourProjectName}/websocket/{principal}
 * <li>观察者模式
 * 
 * 
 * @author svili
 *
 */
@ServerEndpoint(value = "/websocket/{principal}")
public class DefaultWebSocket {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	/** Web Socket连接建立成功的回调方法 */
	@OnOpen
	public void onOpen(@PathParam("principal") String principal, Session session) {

		// create observer,创建连接(http一次握手,将握手状态session持久化保存)
		WebSocketObserver observer = new WebSocketObserver(session);
		// get subject
		WebSocketSubject subject = WebSocketSubject.Holder.getSubject(principal);
		// register observer into subject 借用jdk内的自带观察者模式托管调用,将观察者添加到观察者队列中
		subject.addObserver(observer);

		//移除观察者操作
		//subject.setPrincipal(principal);
		//subject.deleteObserver(observer);

	}

	/** 服务端收到客户端发来的消息 */
	@OnMessage
	public void onMessage(@PathParam("principal") String principal, String message, Session session) {
		// message EX:{"type":"","data":""}
		JSONObject json = JSON.parseObject(message);
		String type = json.getString("type");
		String data = json.getString("data");

		// 对消息的处理,根据义务自行定义。
		// 这里以打印消息为例
		String log = "receive msg from client,principal : " + principal + ", type : " + type + ", data : " + data;
		System.out.println(log);
	}

	/**
	 * @param principal 如果是群体广播,onclose方法对应要做修改,避免当以页面关闭之后,关掉对应session,导致群体广播失败,暂定principal:public为群体广播
	 * @param session
	 */
	@OnClose
	public void onClose(@PathParam("principal") String principal, Session session) {

		// get subject
		WebSocketSubject subject = WebSocketSubject.Holder.getSubject(principal);

		// get observer
		WebSocketObserver observer = new WebSocketObserver(session);
		// delete observer from subject 移除session握手协议
		subject.deleteObserver(observer);
	}

	@OnError
	public void onError(@PathParam("principal") String principal, Session session, Throwable error) {
		throw new RuntimeException("web socket error.", error);
	}

}
